// TestCaseModel
// (c)2007 Mark Bulmahn. mBulmahn@web.de
// License: GPL 2.0
// Project: TestCaseGenerator. http://www.codeplex.com/TestCaseGenerator

using System;
using System.Collections.Generic;
using System.Text;

namespace TestCaseModel
{
	/// <summary>
	/// This class can generate all possible combinations of a given
	/// number of elements with a given number of possible states
	/// per element. The algorithm is very simple so it will calculate
    /// every combination and it is not able to minimize the number of
    /// results as some pairwise algorithms can do.
	/// </summary>
	public class Combination
	{
		// the definition for the element states ("classes per element")
		int[] elementStates = null;

		// the current combination
		int[] combination = null;

		// the number of results
		int numberOfResults = 0;
		protected int NumberOfResults
		{
			get { return numberOfResults; }
		}

		// the number of elements
		int numberOfElements = 0;
        protected int NumberOfElements
		{
			get { return numberOfElements; }
		}

		// an array for the resulting combinations
		int[,] result = null;
        protected int[,] Result
		{
			get { return result; }
		}


		/// <summary>
		/// The constructor
		/// </summary>
		/// <param name="elementStateDef">An integer array with the dimension of each element</param>
		public Combination(int[] elementStateDef)
		{
			Init(elementStateDef);
		}

		public Combination()
		{
		}

        /// <summary>
        /// The Initialization
        /// </summary>
        /// <param name="elementStateDef">This simple array tells the algorithm how many states an element can have. It's simply
        /// an integer value for every element.</param>
		protected void Init(int[] elementStateDef)
		{
			// initialize the element state definition
			numberOfElements = elementStateDef.Length;
			elementStates = new int[numberOfElements];
			elementStates = elementStateDef;

			// our initial combination
			combination = new int[numberOfElements];

			// set the dimension for the result array
			int resultsExpected = 1;
			for (int i = 0; i < numberOfElements; i++)
				resultsExpected *= elementStates[i];
			result = new int[resultsExpected, numberOfElements];
		}

        /// <summary>
        /// This ist the point where our simple algorithm starts ...
        /// </summary>
        protected void Calculate()
		{
			// start the calculation with column 0
			DoCalculate(0);
		}


        /// <summary>
        /// and this is where the magic happens: simply recurse through all
        /// branches of our tree.
        /// </summary>
        /// <param name="column"></param>
		void DoCalculate(int column)
		{
			// iterate all possible states of the given column
			for (int a = 0; a < elementStates[column]; a++)
			{
				// build the current combination
				combination[column] = a;

				// check whether there are more columns to iterate through
				if (column < numberOfElements - 1)
				{
					// if so, then do the same with the next column
					DoCalculate(column + 1);
				}
				else
				{
					// we are done and we can copy our current combination
					// to the result array
					for (int i = 0; i < numberOfElements; i++)
					{
						result[numberOfResults, i] = combination[i];
					}
					numberOfResults++;
				}
			}
		}
	}
}
